package com.czl.common.util;


import cn.hutool.core.codec.Base64;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class NumberConverter {
	public static final char[] Safe_Number_Char = {
			'n', 'f', 'd', 'h', 'e', 'c', '4', 'w', '3', 'y', 'k', 'm', '7', 't', 'p', '5'
		};
	public static final Map<Integer, Integer> Safe_Number_Char_Map = initSafe_Number_Char(Safe_Number_Char);
	
	public static final char[] Safe_Number_30Char = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'z', 'y', 'z', '_'};
	public static final Map<Integer, Integer> Safe_Number_30Char_Map = initSafe_Number_Char(Safe_Number_30Char);

	private static Map<Integer, Integer> initSafe_Number_Char(char[] clist)
	{
		Map<Integer, Integer> m = new HashMap<Integer, Integer>();
		for (int i = 0; i < clist.length; i++)
		{
			m.put((int) clist[i], i);
		}
		return m;
	}

	public static String decToNx(long number, char[] key)
	{
		StringBuffer nstr = new StringBuffer();
		if (number < 0)
			number = 0 - number;
		int wei = key.length;
		while (number >= 0)
		{
			nstr.insert(0, key[(int) (number % wei)]);
			number = number / wei;
			if (number <= 0)
				break;
		}
		return nstr.toString();
	}

	public static long nxToDec(String number, Map<Integer, Integer> map)
	{
		long l = 0;
		if (number != null && number.length() > 0)
		{
			long bei = 1;
			Integer n = 0;
			int wei = map.size();
			for (int i = number.length() - 1; i >= 0; i--)
			{
				n = map.get((int) number.charAt(i));
				if (n == null)
					n = 0;
				l += bei * n;
				bei = bei * wei;
			}
		}
		return l;
	}
	
	/**
	 * 将安全的30进制字符转换成long
	 * 
	 * @param number
	 * @return
	 */
    public static long safe30ToDec(String number)
    {
    	return nxToDec(number, Safe_Number_30Char_Map);
    }
    
    /**
	 * 将long转换成30进制的安全字符
	 * 
	 * @param number
	 * @return
	 */
    public static String decToSafe30(long number)
    {
    	return decToNx(number, Safe_Number_30Char);
    }
	
	/**
	 * 将安全的16进制字符转换成long
	 * @param number
	 * @return
	 */
    public static long safe16ToDec(String number)
    {
    	return nxToDec(number, Safe_Number_Char_Map);
    }
    
    /**
     * 将long转换成16进制的安全字符
     * @param number
     * @return
     */
    public static String decToSafe16(long number)
    {
    	return decToNx(number, Safe_Number_Char);
    }
	
    public static String decToN62(String number)
    {
        return decToN62(Tools.toLong(number));
    }
    
    public static String decToN62(long number)
    {
        String nstr = "";
        if(number < 0)
        	number = 0 - number;
        if(number >= 0)
        {
            while(number > 0)
            {
                nstr = String.valueOf(tranDecTo62(number % 62)) + nstr;
                number = number / 62;
            }
        }
        return nstr;
    }

    public static long n62ToDec(String number)
    {
        long l = 0;
        if(number != null)
        {
            long bei = 1;
            long n = 0;
            for(int i = number.length() - 1;i >= 0;i --)
            {
                n = tran62ToDec(number.charAt(i));
                l += bei * n;
                bei = bei * 62;
            }
        }
        return l;
    }
    
    private static char tranDecTo62(long n)
    {
        if(n >= 0 && n <= 9)
            return (char)(n + '0');
        if(n >= 10 && n <= 35)
            return (char)((n - 10) + 'a');
        if(n >= 36 && n <= 61)
            return (char)((n - 36) + 'A');
        return '0';
    }
    
    private static long tran62ToDec(char c)
    {
        if(c >= '0' && c <= '9')
            return c - '0';
        if(c >= 'a' && c <= 'z')
            return c - 'a' + 10;
        if(c >= 'A' && c <= 'Z')
            return c - 'A' + 36;
        return 0;
    }
    
	public static byte[] HexStringToByteArray(String str)
	{
		if(Tools.stringIsNotNull(str))
		{
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			for(int i = str.length();i > 0;i -= 2)
			{
				out.write(HexStringToInt(str.substring((i-2>0)?(i-2):0, i)));
			}
			try
            {
	            out.flush();
            } catch (IOException e)
            {
            }
			try
            {
	            out.close();
            } catch (IOException e)
            {
            }
			return out.toByteArray();
		}
		return null;
	}
    
	public static byte[] HexStringToByteArrayHeightFirst(String str)
	{
		if(Tools.stringIsNotNull(str))
		{
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			for(int i = 0;i < str.length();i += 2)
			{
				out.write(HexStringToInt(str.substring(i, (i+2<= str.length())?(i+2):i+1)));
			}
			try
            {
	            out.flush();
            } catch (IOException e)
            {
            }
			try
            {
	            out.close();
            } catch (IOException e)
            {
            }
			return out.toByteArray();
		}
		return null;
	}
    
	public static long HexStringToLong(String str)
	{
		long nn = 0;
		if(Tools.stringIsNotNull(str))
		{
			str = str.toUpperCase();
			if(str.matches("[0-9A-F]+"))
			{
				long n = 0;
				for(int i = str.length() - 1, j = 0;i >= 0;i --, j += 4)
				{
					n = (int)str.charAt(i);
					if(n >= '0' && n <= '9')
						n = n & 0x0F;
					else if(n >= 'A' && n <= 'F')
						n = (n & 0x0F) + 9;
					else
						n = 0;
					
					nn += (n << j);
				}
			}
		}
		return nn;
	}
	
	public static String byteArrayToHexString(byte[] byteBuf)
    {
        StringBuffer strbuf = new StringBuffer();
        String temp = "";
        for (int i = 0; i < byteBuf.length; i++)
        {
            temp = Integer.toHexString((int)0xFF & byteBuf[i]).toUpperCase();
            if(temp.length() == 1)
                strbuf.append("0");
            strbuf.append(temp.toUpperCase());
        }
        return strbuf.toString();
    }
    
	public static int HexStringToInt(String str)
	{
		int nn = 0;
		if(Tools.stringIsNotNull(str))
		{
			str = str.toUpperCase();
			if(str.matches("[0-9A-F]+"))
			{
				for(int i = str.length() - 1, j = 0, n = 0;i >= 0;i --, j += 4)
				{
					n = (int)str.charAt(i);
					if(n >= '0' && n <= '9')
						n = n & 0x0F;
					else if(n >= 'A' && n <= 'F')
						n = (n & 0x0F) + 9;
					else
						n = 0;
					
					nn += (n << j);
				}
			}
		}
		return (char)nn;
	}
	
	public static String UUID()
	{
		return UUID.randomUUID().toString();
	}
    public static byte[] asBytes(String id) {   
        UUID uuid=UUID.fromString(id);   
        long msb = uuid.getMostSignificantBits();   
        long lsb = uuid.getLeastSignificantBits();   
        byte[] buffer = new byte[16];   
  
        for (int i = 0; i < 8; i++) {   
                buffer[i] = (byte) (msb >>> 8 * (7 - i));   
        }   
        for (int i = 8; i < 16; i++) {   
                buffer[i] = (byte) (lsb >>> 8 * (7 - i));   
        }   
        return buffer;   
  
    }   

	
	public static String UUIDShort()
	{
		UUID uuid = UUID.randomUUID();
		long msb = uuid.getMostSignificantBits();
		long lsb = uuid.getLeastSignificantBits();
		byte[] buffer = new byte[16];
		for (int i = 0, bei = 8*7; i < 16; i++, bei -= 8)
		{
			buffer[i] = (byte) ((i<8?msb:lsb) >>> bei);
		}
		return Base64.encode(buffer);
	}
	
	// public static void main(String[] par)
	// {
	// 	String s;
	// 	System.out.println(decToN62(9876543210L));
	// 	System.out.println((s=decToSafe30(9876543210L)));
	// 	System.out.println(safe30ToDec(s));
	// 	System.out.println(decToSafe30(0L));
	// 	System.out.println(safe30ToDec("0"));
	// }
}
